﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.ComponentModel.Design.Serialization
Imports System.Reflection
Imports System.Text
Imports System.Workflow.ComponentModel.Design
Imports System.Xml

Namespace System.Workflow.ComponentModel.Serialization
    Friend Class MarkupExtensionSerializer
        Inherits WorkflowMarkupSerializer
        ' Methods
        Protected Friend NotOverridable Overrides Function CanSerializeToString(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As Boolean
            Return True
        End Function

        Private Function CreateEscapedValue(ByVal value As String) As String
            If (value Is Nothing) Then
                Throw New ArgumentNullException("value")
            End If
            Dim builder As New StringBuilder(&H40)
            Dim length As Integer = value.Length
            Dim i As Integer
            For i = 0 To length - 1
                If ("=,""'{}\".IndexOf(value.Chars(i)) <> -1) Then
                    builder.Append("\")
                End If
                builder.Append(value.Chars(i))
            Next i
            Return builder.ToString
        End Function

        Protected Overridable Function GetInstanceDescriptor(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As InstanceDescriptor
            Dim extension As MarkupExtension = [TryCast](value,MarkupExtension)
            If (extension Is Nothing) Then
                Throw New ArgumentException(SR.GetString("Error_UnexpectedArgumentType", New Object() { GetType(MarkupExtension).FullName }), "value")
            End If
            Return New InstanceDescriptor(extension.GetType.GetConstructor(New Type(0  - 1) {}), Nothing)
        End Function

        Protected Friend NotOverridable Overrides Function SerializeToString(ByVal serializationManager As WorkflowMarkupSerializationManager, ByVal value As Object) As String
            If (serializationManager Is Nothing) Then
                Throw New ArgumentNullException("serializationManager")
            End If
            Dim writer As XmlWriter = [TryCast](serializationManager.WorkflowMarkupStack.Item(GetType(XmlWriter)),XmlWriter)
            If (writer Is Nothing) Then
                Throw New ArgumentNullException("writer")
            End If
            If (value Is Nothing) Then
                Throw New ArgumentNullException("value")
            End If
            writer.WriteString("{")
            Dim prefix As String = String.Empty
            Dim xmlQualifiedName As XmlQualifiedName = serializationManager.GetXmlQualifiedName(value.GetType, prefix)
            writer.WriteQualifiedName(xmlQualifiedName.Name, xmlQualifiedName.Namespace)
            Dim num As Integer = 0
            Dim dictionary As Dictionary([Of] String, String) = Nothing
            Dim instanceDescriptor As InstanceDescriptor = Me.GetInstanceDescriptor(serializationManager, value)
            If (Not instanceDescriptor Is Nothing) Then
                Dim memberInfo As ConstructorInfo = [TryCast](instanceDescriptor.MemberInfo,ConstructorInfo)
                If (Not memberInfo Is Nothing) Then
                    Dim parameters As ParameterInfo() = memberInfo.GetParameters
                    If ((Not parameters Is Nothing) AndAlso (parameters.Length = instanceDescriptor.Arguments.Count)) Then
                        Dim index As Integer = 0
                        Dim obj2 As Object
                        For Each obj2 In instanceDescriptor.Arguments
                            If (dictionary Is Nothing) Then
                                dictionary = New Dictionary([Of] String, String)
                            End If
                            If (Not obj2 Is Nothing) Then
                                dictionary.Add(parameters(index).Name, parameters(index++).Name)
                                If (num++ > 0) Then
                                    writer.WriteString(",")
                                Else
                                    writer.WriteString(" ")
                                End If
                                If (obj2.GetType Is GetType(String)) Then
                                    writer.WriteString(Me.CreateEscapedValue([TryCast](obj2,String)))
                                    [Continue] For
                                End If
                                If TypeOf obj2 Is Type Then
                                    Dim type As Type = [TryCast](obj2,Type)
                                    If (Not type.Assembly Is Nothing) Then
                                        Dim str2 As String = String.Empty
                                        Dim name2 As XmlQualifiedName = serializationManager.GetXmlQualifiedName(type, str2)
                                        writer.WriteQualifiedName(XmlConvert.EncodeName(name2.Name), name2.Namespace)
                                    Else
                                        writer.WriteString(type.FullName)
                                    End If
                                    [Continue] For
                                End If
                                Dim text As String = MyBase.SerializeToString(serializationManager, obj2)
                                If (Not [text] Is Nothing) Then
                                    writer.WriteString([text])
                                End If
                            End If
                        Next
                    End If
                End If
            End If
            Dim list As New List([Of] PropertyInfo)
            list.AddRange(Me.GetProperties(serializationManager, value))
            list.AddRange(serializationManager.GetExtendedProperties(value))
            Dim info2 As PropertyInfo
            For Each info2 In list
                If (((Helpers.GetSerializationVisibility(info2) <> DesignerSerializationVisibility.Hidden) AndAlso info2.CanRead) AndAlso (Not info2.GetValue(value, Nothing) Is Nothing)) Then
                    Dim serializer As WorkflowMarkupSerializer = [TryCast](serializationManager.GetSerializer(info2.PropertyType, GetType(WorkflowMarkupSerializer)),WorkflowMarkupSerializer)
                    If (serializer Is Nothing) Then
                        serializationManager.ReportError(New WorkflowMarkupSerializationException(SR.GetString("Error_SerializerNotAvailable", New Object() { info2.PropertyType.FullName })))
                    Else
                        If (Not dictionary Is Nothing) Then
                            Dim customAttributes As Object() = info2.GetCustomAttributes(GetType(ConstructorArgumentAttribute), False)
                            If ((customAttributes.Length > 0) AndAlso dictionary.ContainsKey([TryCast](customAttributes(0),ConstructorArgumentAttribute).ArgumentName)) Then
                                [Continue] For
                            End If
                        End If
                        serializationManager.Context.Push(info2)
                        Try 
                            Try 
                                Dim obj3 As Object = info2.GetValue(value, Nothing)
                                If serializer.ShouldSerializeValue(serializationManager, obj3) Then
                                    If serializer.CanSerializeToString(serializationManager, obj3) Then
                                        If (num++ > 0) Then
                                            writer.WriteString(",")
                                        Else
                                            writer.WriteString(" ")
                                        End If
                                        writer.WriteString(info2.Name)
                                        writer.WriteString("=")
                                        If (obj3.GetType Is GetType(String)) Then
                                            writer.WriteString(Me.CreateEscapedValue([TryCast](obj3,String)))
                                        Else
                                            Dim str4 As String = serializer.SerializeToString(serializationManager, obj3)
                                            If (Not str4 Is Nothing) Then
                                                writer.WriteString(str4)
                                            End If
                                        End If
                                    Else
                                        serializationManager.ReportError(New WorkflowMarkupSerializationException(SR.GetString("Error_SerializerNoSerializeLogic", New Object() { info2.Name, value.GetType.FullName })))
                                    End If
                                End If
                            Catch obj1 As Object
                                serializationManager.ReportError(New WorkflowMarkupSerializationException(SR.GetString("Error_SerializerNoSerializeLogic", New Object() { info2.Name, value.GetType.FullName })))
                            End Try
                            [Continue] For
                        Finally
                            serializationManager.Context.Pop
                        End Try
                    End If
                End If
            Next
            writer.WriteString("}")
            Return String.Empty
        End Function


        ' Fields
        Private Const CompactFormatCharacters As String = "=,""'{}\"
        Private Const CompactFormatEnd As String = "}"
        Private Const CompactFormatNameValueSeperator As String = "="
        Private Const CompactFormatPropertySeperator As String = ","
        Private Const CompactFormatStart As String = "{"
        Private Const CompactFormatTypeSeperator As String = " "
    End Class
End Namespace

